package com.sky.aspect;


import com.github.xiaoymin.knife4j.core.util.StrUtil;
import com.sky.constant.JwtClaimsConstant;
import com.sky.context.BaseContext;
import com.sky.mapper.GlobalAspectMapper;
import com.sky.operateLog.OperateLog;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * 编写一个全球性的 记录日志
 */

@Component
//开启一个切面 记录我需要 去记录日志的类
@Aspect
@Slf4j
public class GlobalAspect {
    //不需要了 垃圾东西 我通过threadlocal拿到了id
    //获取请求头中的token
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private GlobalAspectMapper globalAspectMapper;


        //表明我这个aop是给这个注解来增强方法的
        @Around("@annotation(com.sky.annotation.MyLog)")
        //开启事务 传播行为 为其他事务如果抛出异常了 我的功能还是必须执行
//        @Transactional(propagation = Propagation.REQUIRES_NEW)
        public Object global(ProceedingJoinPoint joinPoint) throws Throwable {
//            //1获取第一个数据  操作人的id
//            //1.2 通过HttpServletRequest获取 请求头中的token
//            String token = request.getHeader("token");
//            //1.3将token进行解析
//            Claims claims = JwtUtil.parseJWT("empId",token);
//            //1.4获取到了 token  我要拿到里面的id
//            Integer operateUser = (Integer) claims.get("id"); //强转为 Integer的id  因为实体类是这个


            Long currentId = BaseContext.getCurrentId();
            //2获取到操作时间
            LocalDateTime operateTime = LocalDateTime.now();
            //3获取操作类名
            String className = joinPoint.getTarget().getClass().getName();
            //4获取操作方法名
            String methodName = joinPoint.getSignature().getName();
            //5获取操作方法的参数
            Object[] joinPointArgs = joinPoint.getArgs();
            //5.1因为它是数组 所以要强转为tostring类型
            String methodParams = Arrays.toString(joinPointArgs);
            //6获取操作方法的返回值
            //TODO 1编写aop获取操作日志 不会写返回值
            //7获取到这个aop进行了多久
            long start = System.currentTimeMillis();
            Object proceed = joinPoint.proceed();
            long end = System.currentTimeMillis();
            //7.1获取操作时间
            Long costTime=end-start;
            //8如果 操作时间大于200毫秒 则需要进行优化
            Integer optimiZe=0;
            if (costTime>200){
                optimiZe=1;
            }

            //8 最终操作 将数据写入数据库中
            OperateLog operateLog = new OperateLog(
                    null,
                    currentId,
                    operateTime,
                    className,
                    methodName,
                    methodParams,
                    null,
                    costTime,optimiZe);
            globalAspectMapper.aspect(operateLog);
            return proceed;
        }

}



















